﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace BigPang.Render
{
    public class SpriteHitEventArgs : EventArgs
    {
        public Sprite Target;
    }

    public class Sprite : Renderable
    {
        public object Tag;

        public event EventHandler<SpriteHitEventArgs> OnHit;

        public enum Direction
        {
            Unknown = -1,
            Down,
            Left,
            Right,
            Up,
        }

        float mSpeed;
        int mStartTime;
        Bitmap mBitmap;
        int mFrameCount;

        public const int FrameFPS = 10;
        static Font mFont = new Font("宋体", 9);
        SolidBrush mFontBrush = new SolidBrush(Color.DarkSlateBlue);
        static SolidBrush mFontOutBrush = new SolidBrush(Color.White);

        ImageAttributes mIa = new ImageAttributes();
        ColorMatrix cm = new ColorMatrix();

        public const int HUDOffset = 12;

        public string HUD { get; set; }

        static List<Sprite> mSpriteList = new List<Sprite>();

        public Direction mDirection;
        public Sprite mSource;

        public bool IsMoving { get; private set; }

        Color mColor;
        public Color CoverColor
        {
            get { return mColor; }
            set
            {
                mColor = value;

                cm[0, 0] = mColor.R / 255.0f;
                cm[1, 1] = mColor.G / 255.0f;
                cm[2, 2] = mColor.B / 255.0f;
                cm[3, 3] = mColor.A / 255.0f;

                mIa.SetColorMatrix(cm);

                mFontBrush = new SolidBrush(mColor);
            }
        }

        Color mAddColor;
        public Color AddColor
        {
            get { return mAddColor; }
            set
            {
                mColor = value;

                cm[4, 0] = mAddColor.R / 255.0f;
                cm[4, 1] = mAddColor.G / 255.0f;
                cm[4, 2] = mAddColor.B / 255.0f;
                cm[4, 3] = mAddColor.A / 255.0f;

                mIa.SetColorMatrix(cm);

                //mFontBrush = new SolidBrush(mColor);
            }
        }

        Point mPosition;

        public Size Size { get; set; }

        public Effect MountEffect;

        public Rectangle SrcRect
        {
            get
            {
                if (IsMoving)
                {
                    int nowTime = Environment.TickCount;
                    float length = ((nowTime - mStartTime) / 1000.0f) * FrameFPS;

                    int frame = (int)length % mFrameCount;

                    return new Rectangle(new Point( frame * this.Size.Width, (int)mDirection * this.Size.Height), this.Size);
                }
                else
                {
                    return new Rectangle(new Point(0, (int)mDirection * this.Size.Height ), this.Size);
                }
            }
        }

        public override void RegisterRender()
        {
            base.RegisterRender();

            mSpriteList.Add(this);
        }

        public override void UnregisterRender()
        {
            mSpriteList.Remove(this);

            base.UnregisterRender();
        }

        public Rectangle RenderRect
        {
            get
            {
                return new Rectangle(RenderPosition, this.Size);
            }
        }

        public Point RenderPosition 
        {
            get
            {
                if (IsMoving)
                {
                    int nowTime = Environment.TickCount;
                    float length = ((nowTime - mStartTime) / 1000.0f) * mSpeed;
                    Point p = mPosition;
                    switch (mDirection)
                    {
                        case Direction.Down:
                            p.Y += (int)length;
                            break;
                        case Direction.Up:
                            p.Y -= (int)length;
                            break;
                        case Direction.Left:
                            p.X -= (int)length;
                            break;
                        case Direction.Right:
                            p.X += (int)length;
                            break;
                    }

                    return p;
                }
                else
                {
                    return mPosition;
                }
            }
        }

        public Sprite( string imageFileName, int frameCount = 4 )
        {
            mBitmap = Bitmap.FromFile(imageFileName) as Bitmap;

            Size = new Size(mBitmap.Width / frameCount, mBitmap.Height / 4);

            mFrameCount = frameCount;

            CoverColor = Color.FromArgb(255, 255, 255, 255);
        }

        public void StartMove( Direction dir, float speed )
        {
            if (IsMoving)
                mPosition = RenderPosition;

            mStartTime = Environment.TickCount;
            mDirection = dir;
            mSpeed = speed;
            IsMoving = true;
        }

        public void StopMove()
        {
            mPosition = RenderPosition;
            IsMoving = false;
        }

        public void SetPosition(int x, int y)
        {
            mPosition.X = x;
            mPosition.Y = y;
        }

        public override void OnRender(Graphics graph)
        {
            //graph.DrawRectangle(new Pen(new SolidBrush(Color.White)), RenderRect);
            Point p = RenderPosition;

            if (IsMoving)
            {
                foreach (Sprite s in mSpriteList)
                {
                    // 不与自身发生碰撞
                    if (s == this)
                        continue;

                    // 不与发射器碰撞
                    if (s == mSource)
                        continue;

                    if (RenderRect.IntersectsWith(s.RenderRect))
                    {
                        SpriteHitEventArgs e = new SpriteHitEventArgs();
                        e.Target = s;

                        if (OnHit != null)
                        {
                            OnHit(this, e);
                            break;
                        }
                    }
                }
            }

            if (MountEffect != null)
            {
                int x = p.X + this.Size.Width / 2 - MountEffect.Size.Width / 2;
                int y = p.Y + this.Size.Height / 2 - MountEffect.Size.Height / 2;

                MountEffect.SetPosition(x, y);
            }

            
            //graph.DrawImage(mBitmap, new Rectangle(p.X,p.Y, this.Size.Width, this.Size.Height), SrcRect, GraphicsUnit.Pixel);
            graph.DrawImage(mBitmap, new Rectangle(p.X, p.Y, this.Size.Width, this.Size.Height), SrcRect.X, SrcRect.Y, SrcRect.Width, SrcRect.Height, GraphicsUnit.Pixel, mIa);
            
            graph.DrawString(HUD, mFont, mFontOutBrush, p.X + 1, p.Y - HUDOffset);
            graph.DrawString(HUD, mFont, mFontOutBrush, p.X - 1, p.Y - HUDOffset);
            graph.DrawString(HUD, mFont, mFontOutBrush, p.X, p.Y - HUDOffset + 1);
            graph.DrawString(HUD, mFont, mFontOutBrush, p.X, p.Y - HUDOffset - 1);

            graph.DrawString(HUD, mFont, mFontBrush, p.X, p.Y - HUDOffset);
        }
    }
}
